// EMERGENT GAME TECHNOLOGIES PROPRIETARY INFORMATION
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Emergent Game Technologies and may not 
// be copied or disclosed except in accordance with the terms of that 
// agreement.
//
//      Copyright (c) 1996-2008 Emergent Game Technologies.
//      All Rights Reserved.
//
// Emergent Game Technologies, Chapel Hill, North Carolina 27517
// http://www.emergent.net

//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
GnTPointerListBase<TheAllocator,T>::~GnTPointerListBase() 
{
    // RemoveAll is called from here because it depends on virtual functions
    // implemented in the derived class.
    // It will also be called in the parent destructor, 
    // but the map will already be empty.
    GnTPointerListBase<TheAllocator,T>::RemoveAll();
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
GnTListItem<T>* GnTPointerListBase<TheAllocator,T>::NewItem()
{
    return (GnTListItem<T>*)GnTListBase<TheAllocator,
        T>::m_kAllocator.Allocate();
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
void GnTPointerListBase<TheAllocator,T>::DeleteItem(GnTListItem<T>* pkItem)
{
    pkItem->m_element = 0;
    GnTListBase<TheAllocator,T>::m_kAllocator.Deallocate(pkItem);
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
const T& GnTPointerListBase<TheAllocator,T>::GetHead() const
{
    return GnTListBase<TheAllocator,T>::m_pkHead->m_element;
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
const T& GnTPointerListBase<TheAllocator,T>::GetTail() const
{
    return GnTListBase<TheAllocator,T>::m_pkTail->m_element;
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
const T& GnTPointerListBase<TheAllocator,T>::GetNext(GnTListIterator& kPos)
    const
{
    GnAssert(kPos != 0);

    const T& element= ((GnTListItem<T>*) kPos)->m_element;

    kPos = ((GnTListItem<T>*) kPos)->m_pkNext;
    return element;
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
const T& GnTPointerListBase<TheAllocator,T>::GetPrev(GnTListIterator& kPos)
    const
{
    GnAssert(kPos != 0);

    const T& element= ((GnTListItem<T>*) kPos)->m_element;
    kPos = ((GnTListItem<T>*) kPos)->m_pkPrev;

    return element;
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
const T& GnTPointerListBase<TheAllocator,T>::Get(GnTListIterator kPos) const
{
    GnAssert(kPos != 0);
    return ((GnTListItem<T>*) kPos)->m_element;
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
T GnTPointerListBase<TheAllocator,T>::RemoveHead()
{
    GnAssert((GnTListBase<TheAllocator,T>::m_pkHead));

    GnTListItem<T>* pkNode = GnTListBase<TheAllocator,T>::m_pkHead;

    GnTListBase<TheAllocator,T>::m_pkHead = GnTListBase<TheAllocator,
        T>::m_pkHead->m_pkNext;
 
    if (GnTListBase<TheAllocator,T>::m_pkHead)
        GnTListBase<TheAllocator,T>::m_pkHead->m_pkPrev = 0;
    else
        GnTListBase<TheAllocator,T>::m_pkTail = 0;
 
    T element = pkNode->m_element;
 
    DeleteItem(pkNode);

    GnTListBase<TheAllocator,T>::m_kAllocator.m_uiCount--;

    return element;
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
T GnTPointerListBase<TheAllocator,T>::RemoveTail()
{
    GnAssert((GnTListBase<TheAllocator,T>::m_pkTail));
 
    GnTListItem<T>* pkNode = GnTListBase<TheAllocator,T>::m_pkTail;

    GnTListBase<TheAllocator,T>::m_pkTail = GnTListBase<TheAllocator,
        T>::m_pkTail->m_pkPrev;
 
    if (GnTListBase<TheAllocator,T>::m_pkTail)
        GnTListBase<TheAllocator,T>::m_pkTail->m_pkNext = 0;
    else
        GnTListBase<TheAllocator,T>::m_pkHead = 0;
 
    T element = pkNode->m_element;
 
    DeleteItem(pkNode);

    GnTListBase<TheAllocator,T>::m_kAllocator.m_uiCount--;
 
    return element;
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
T GnTPointerListBase<TheAllocator,T>::RemovePos(GnTListIterator& kPos)
{
    GnTListItem<T>* pkNode = (GnTListItem<T>*) kPos;

    GnAssert(pkNode);

    if (pkNode == GnTListBase<TheAllocator,T>::m_pkHead)
    {
        kPos = pkNode->m_pkNext; // kPos points to new head
        return RemoveHead();
    }
    if (pkNode == GnTListBase<TheAllocator,T>::m_pkTail)
    {
        kPos = 0; // kPos has walked off end of list
        return RemoveTail();
    }

    GnTListItem<T>* pkPrev = pkNode->m_pkPrev;
    GnTListItem<T>* pkNext = pkNode->m_pkNext;

    kPos = pkNext;
 
    if (pkPrev)
        pkPrev->m_pkNext = pkNext;
    if (pkNext)
        pkNext->m_pkPrev = pkPrev;
 
    T element = pkNode->m_element;
 
    DeleteItem(pkNode);
 
    GnTListBase<TheAllocator,T>::m_kAllocator.m_uiCount--;
 
    return element;
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
GnTListIterator GnTPointerListBase<TheAllocator,T>::
    InsertAfter(GnTListIterator kPos, const T& element)
{
    GnAssert(kPos);

    GnTListItem<T>* pkNode;
    pkNode = (GnTListItem<T>*) NewItem();

    pkNode->m_element = element;

    return AddNodeAfter(kPos,pkNode);
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
GnTListIterator GnTPointerListBase<TheAllocator,T>::
    InsertBefore(GnTListIterator kPos, const T& element)
{
    GnAssert(kPos);

    GnTListItem<T>* pkNode;
    pkNode = (GnTListItem<T>*) NewItem();

    pkNode->m_element = element;

    return AddNodeBefore(kPos,pkNode);
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
void GnTPointerListBase<TheAllocator,T>::AddHead(const T& element)
{
    GnTListItem<T>* pkNode;
    pkNode = (GnTListItem<T>*) NewItem();

    pkNode->m_element = element;
    
    AddNodeHead(pkNode);
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
void GnTPointerListBase<TheAllocator,T>::AddTail(const T& element)
{
    GnTListItem<T>* pkNode;
    pkNode = (GnTListItem<T>*) NewItem();

    pkNode->m_element = element;

    AddNodeTail(pkNode);
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
T GnTPointerListBase<TheAllocator,T>::Remove(const T& element)
{
    GnTListIterator kPos = GnTPointerListBase<TheAllocator,T>::FindPos(
        element);

    return kPos ? RemovePos(kPos) : element;
}
//---------------------------------------------------------------------------
template <class TheAllocator, class T> inline
GnTListIterator GnTPointerListBase<TheAllocator,T>::
    FindPos(const T& element, GnTListIterator kStart) const
{
    if (kStart == 0)
        kStart = GnTPointerListBase<TheAllocator,T>::GetHeadPos();
    
    while (kStart)
    {
        GnTListIterator kPos = kStart;
        if (element == GetNext(kStart))
            return kPos;
    }
    return 0;
}
//---------------------------------------------------------------------------
